// JavaScript性能优化

// JavaScript中的可达对象

// 可以访问到的对象就是可达对象（引用、作用域链）
// 可达的标准就是从根出发是否能够被找到
// JavaScript中的根可以理解为全局变量对象


// 1、GC算法
// GC就是垃圾回收机制的简写，GC可以找到内存中的垃圾，并释放和回收空间，GC中的垃圾：程序中不再需要使用的对象、程序中不能访问到的对象。常见的GC算法：引用计数、标记清除、标记整理、分代回收

// 1、引用计数
// 核心思想是设置引用数，判断当前引用数是否为0，引用关系改变的时候会修改引用数字，引用数字变为0立即回收。

// 优点：发现垃圾时立即回收，最大限度减少程序暂停
// 缺点：对象之间互有引用的情况，即使对象本身没有被使用，但是引用存在就导致了引用计数不为0，无法被回收的情况。

// 详：如果一个对象的引用数为0，则该对象将被回收。程序运行时，对内存的消耗除逻辑代码外，也包括了GC算法的消耗，引用计数固然可以在程序出现垃圾的时候可以及时回收释放内存，也因内存可以不断得到释放而减少了程序暂停的时间，但是GC同时也需要维护‘roots’表来统计引用计数，当代码中引用较多时，也会带来损耗。同时对于 对象之间互有引用的情况，即使对象本身没有被使用，但是引用存在就导致了引用计数不为0，无法被回收的情况。

// 2、标记清除
// 标记清除算法会递归的寻找对象之间的引用获取所有可达对象，并为其做上标记, 但是标记清除算法所回收的内存地址在内存上不一定是连续的，这就导致了内存空间的碎片化(类似磁盘碎片), 浪费空间，并且标记清除法是不会立即回收对象的，而且当标记清除法运行当时候，程序会被暂停。

// 分为标记/清除俩阶段
// 遍历所有对象，寻找活动的对象
// 遍历所有对象清除没有被标记的对象
// 回收相应的空间
// 3、标记整理算法
// 标记整理算法增强了标记清除算法，其在回收对象前会将对象的地址进行移动，使其在地址上连续，然后再回收.

// 2、V8
// V8是一款主流的JavaScript的执行引擎，v8采用及时编译，V8内存设有上限，

// V8垃圾回收策略

// 采用分代回收的思想
// 内存分为新生代、老生代
// 针对不同对象采用不同算法
// V8中常用的GC算法

// 分代回收、空间复制、标记清除、标记整理、标记增量

// 新生代回收实现

// 新生代对象：存活时间比较短

// 1、回收过程采用复制算法+标记整理

// 2、新生代内存区分为两个等大小的空间

// 3、使用空间为from，空闲空间为to

// 4、活动对象存储于From空间

// 5、标记整理后将活动对象拷贝到To

// 6、From与To交换空间完成释放

// 老生代回收实现

// 1、主要采用标记清除、标记整理、增量标记的GC算法

// 2、首先采用标记清除完成垃圾空间的回收

// 3、采用标记整理进行空间优化

// 老生代区域大小约1.4G(32位大小为700M)，老生代存放的对象为存活时间较长的对象，一般为window下的变量或被闭包保存的变量。
// 老生代区域采用标记清除，标记整理，增量标记的GC算法。首先使用标记清除完成对垃圾空间的回收，当新生代区域出现晋升现象时，如果老生代空间不足，则会使用标记整理进行空间优化。同时在老生代变量进行回收的时候也会采用增量标记算法进行效率优化。
// 增量标记是对标记清除算法对优化，让其不会一口气的去寻找到所有活动对象。而是会穿插在程序的运行中执行，降低了程序的卡顿，当标记彻底采集完毕之后，才会把程序停下来，进行垃圾回收。